dso(5)									dso(5)

NAME
     DSO - Dynamic Shared Object

TOPIC
     This man page is intended to be both a quick reference and	a source of
     detailed information on Dynamic Shared Objects.  It is divided into 4
     sections:

     General Information and Overview

     Linking/Building Suggestions

     Performance Considerations

     Frequently	Asked Questions	and Detailed Discussions

GENERAL	INFORMATION AND	OVERVIEW
   Format
     A DSO, or Dynamic Shared Object, is an ELF	format object file, very
     similar in	structure to an	executable program but with no "main".	It has
     a shared component, consisting of shared text and read-only data; a
     private component,	consisting of data and the GOT (Global Offset Table);
     several sections that hold	information necessary to load and link the
     object; and a liblist, the	list of	other shared objects referenced	by
     this object. Most of the libraries	supplied by SGI	are available as
     dynamic shared objects.

   PIC -- Position Independent Code
     A DSO is relocatable at runtime; it can be	loaded at any virtual address.
     A consequence of this is that all references to external symbols must be
     resolved at runtime.  References from the private region (.e.g. from
     private data) are resolved	once at	load-time; references from the shared
     region (e.g. from shared text) must go through an indirection table (GOT)
     and hence have a small performance	penalty	associated with	them.

     Code compiled for use in a	shared object is referred to as	PIC whereas
     non-PIC is	usually	referred to as non-shared. Non-shared code and PIC can
     not be mixed in the same object.

   What	Happens	at Runtime?
     Exec loads	the main program and then loads	rld(1),	the runtime linking
     loader, which finishes the	exec operation.	 Starting with main's liblist,
     rld loads each shared object on the list that is not marked as delay
     load, reads that object's liblist,	and repeats the	operation until	all
     shared objects have been loaded.  Next, rld allocates common and fixes up
     symbolic references in each loaded	object.	 (This is necessary because we
     don't know	until runtime where the	object will be loaded.)	 Next, each
     object's init code	is executed.  Finally, control is transferred to
     "__start".

     Be	sure to	read about quickstart, delayed loads, sgidladd(3), and
     dlopen(3) as each can affect this general process.

LINKING	/ BUILDING DYNAMIC SHARED OBJECTS
   Example
     Suppose your library is in	an archive libfoo.a of object files all	of
     which have	been compiled -shared; and it references symbols found in
     libc.so, libgl.so,	libX11.so and libnetls.so though most programs will
     never use the path	that requires libnetls.so. SGI recommends building
     your DSO, libfoo.so, in the following way:

	  ld			       \
	       -elf		       \
	       -shared		       \
	       -no_unresolved	       \
	       -rdata_shared	       \
	       -o libfoo.so	       \
	       -all libfoo.a	       \
	       -lX11		       \
	       -delay_load -lnetls     \
	       -lc		       \
	       -lgl

     This builds a DSO called libfoo.so	that will request rld to load libc.so,
     libX11.so,	and libgl.so  whenever libfoo.so is loaded and will load
     libnetls.so if it is ever referenced.

     NOTE:
	  If you have any C++ object files among the objects making up your
	  DSO, you must	replace	ld in the above	command	with CC. I.e. your
	  command will become:

	       CC -elf -shared ... -o libfoo.so	-all libfoo.a ...

	  However, you do not have to do anything special at all to use	such
	  C++ DSOs when	linking	other programs against these DSOs.  So you can
	  link such DSOs into C, C++ or	Fortran	programs using your usual link
	  commands, or link other DSOs against these C++ DSOs, without taking
	  any special action.

	  For example, the following link will work, with the preceding	C++
	  DSO libfoo.so	being properly initialized by rld at program startup:

	       f77 fortran_prog.o -lfoo

   Controlling The Symbols Exported By A Dynamic Shared	Object
     In	building a dynamic shared object it is necessary that the control is
     maintained	over which symbols are exported	by that	object.	 One of	the
     benefits of using dynamic shared objects is the ability to	release	new
     versions of that object and still have objects that were linked against
     the old version, work with	the new	version.  This will be impossible to
     guarantee,	if the set of symbols exported by an object can	not easily be
     understood	by object's creator.  ld provides several options that will
     aid the developer in controlling which symbols are	exported by a dynamic
     shared object.

     By	default	ld will	not export symbols that	are supplied by	a linked-in
     archive or	dynamic	shared object.	In either of these cases the developer
     is	probably only a	consumer of the	linked-in object, not an exporter. In
     a subsequent release, the developer may not require the linked-in object
     and if the	symbols	provided by the	linked-in object had been exported by
     the developer's object, the new object would not longer be	upwardly
     compatible	with the original version. This	behavior can be	overridden
     using the -exports	option.	 This behavior,	with respect to	archives, is
     also overriden when building a dynamic shared object from an archive
     using the -all option.

     The developer can provide even greater control over the list of symbols
     that are exported using options -exported_symbol, -exports_file, -
     hidden_symbol, or -hides_file. The	first two options lets the developer
     specifically list the symbols that	are to be exported by the dynamic
     shared object.  The -exported_symbol option is followed by	a comma
     separated list of names.  The -exports_file option	gives a	filename that
     contains a	space separated	(including newlines) list of names.  If	any
     symbols are specifically exported,	then only those	symbols	will be
     exported.	All other symbols are automatically hidden.  The last two
     options lets the developer	specify	a list of symbols that are to be not
     exported by the dynamic shared object.

     There are two consequences	of hiding symbols.  First, those symbols will
     not provide resolution to any undefines in	an object that links in	the
     dynamic shared object.  Second , any references to	that symbol within the
     dynamic shared object will	be resolved internally to the hidden symbol.

   Rules Of Thumb
     Use -no_resolved to find unresolved symbols.  While it is not always
     possible to supply	on the link line all the shared	objects	that will be
     referenced	by libfoo.so, in general, libraries should be self-contained.
     This is especially	true for subsequent releases of	a dynamic shared
     object.  If a dynamic shared object has any unresolved references,	they
     must be resolved by some other loaded object.  Having unresolved symbols
     invites disaster since there is no	guarantee that the symbols will	be
     resolved and thus the application will not	run.

     Link against the minimum set of .so's needed.  Loading a shared object
     does carry	a cost.	 Linking against unneeded dynamic shared objects will
     cause them	to be loaded even if they are never referenced.	 ld will
     provide a warning when you	have linked against a dynamic shared object
     that resolves no symbols.

     When building a c++ dynamic shared	object,	specify	-exports for any
     dynamic shared object that	provides the definitions of classes that
     classes in	the object being created derive	from.  Specifying -exports in
     this case will make sure consumers	of the object being created will be
     able to create subclasses of classes provided by that object, without
     having to know the	complete set of	dynamic	shared objects that will need
     to	be loaded.  Using the -exports flag in this case may bring in unwanted
     symbols.  In that case using the -exported_symbol,	-exports_file, -
     hidden_symbol, or -hides_file. options may	be necessary.

     Use -rdata_shared to move all read-only data into the shared segment.
     Unfortunately, there are many programs that write to supposedly read-only
     data; for this reason, this option	is off by default.  The	compiler
     option, -use_readonly_const, is on	by default.

     If	you reference the gl, have it last in the link line.  Often libgl.so
     cannot be quickstarted (see below); putting it last allows	all the
     "upstream"	objects	to still be quickstarted.  You can also	choose to
     delay load	libgl.so. This will still allow	your application to
     quickstart.

     Anytime a "downstream" shared object (a referenced	object)	changes, you
     should relink in order to quickstart.

     Try to minimize inter-DSO data references.

     Try to minimize the use of	global data.  In DSO's,	it is generally	more
     efficient to malloc space when needed rather than use a large static data
     structure.

     Try to pack data together that is likely to be unmodified.	 This allows
     the kernel	to make	more of	the data pages shared, copy-on-write.

     Use the -delay_load option	on any shared object on	the link line that is
     not often used.  This adds	a small	performance penalty for	references to
     it, but can save time and memory for those	programs that don't use	it.

     Do	not call sproc from any	code that may be executed at init time.

PERFORMANCE CONSIDERATIONS
   Quickstart
     When building a shared object or an executable, ld	assigns	addresses to
     the object	and attempts to	resolve	all references.	 At runtime, if	rld
     verifies that the same set	of objects are loaded at the original
     addresses,	then rld can skip all the runtime relocation work and let the
     program run.  This	saves time by skipping doing the relocations and saves
     memory since rld does not have to read in the sections that hold the
     relocation	information.

     At	static link time, ld will resolve any unresolved function calls	to a
     stub routine which	references an rld function called lazy_text_resolve().
     When invoked at runtime, it performs the relocation needed	for all	future
     calls to the original function.   In this way, more programs can quick
     start even	if some	of the function	references are not resolved at static
     link time.

     Quickstart	will fail whenever the dynamic shared objects on a system do
     not match the objects used	when linking and application or	the shared
     objects that it depends on.  This will occur whenever a new version of a
     dynamic shared object is released.	 When quickstart fails rld has to do a
     significant amount	of work.  The rqs(1) command can be used  to
     recalculate the quickstart	information associated with an application or
     a dynamic shared object.  rqs must	be called in proper order so that
     dynamic shared objects on an objects liblist are requickstarted before
     the object	ir requickstarted. rqs will rewrite the	object it is
     requickstarting back in place.  It	is possible to mark an object as non-
     requickstartable by using the -no_rqs flag	to ld.

   Avoiding Gratuitous Shared Object Loads
     Since for each shared object that is loaded, rld does a considerable
     amount of work and	can use	up large amounts of real memory,  it is
     advantageous to not link against shared objects that are not needed.

   Reducing the	number of Conflicts
     Whenever more than	one shared object (including the main program) needed
     by	an executable defines uses the same name for a symbol, this is called
     a conflict	and the	name for which multiple	definitions exist is recorded
     in	your program in	the section named ".conflict"  The names of all
     conflicting symbols pertaining to a program can be	obtained via the -Dc
     flag to elfdump. One example of a conflict	is the routine malloc which is
     defined both in libc.so.1 and in libmalloc.so.

     Conflicts represent extra work to be done at startup, because the
     presence of a conflict means that the objects in the link may not have
     chosen a consistent instance of the symbol	in question.  This extra work
     is	memory-intensive, since	even the presence of one conflict may mean
     that many pages of	memory must be examined	by rld which would otherwise
     have not been needed for a	quickstarting program.	Using the
     -quickstart_info flag will	make ld	print out a warning about every
     conflict it finds and the names of	two of the objects in which it is
     defined.  Of course, sometimes conflicts are a necessary part of the
     design of certain applications.

   dlopen(3), sgidladd(3), and delayed loads
     The overhead associated with objects that are referenced but seldom
     actually used can be mitigated by using dlopen(3),	sgidladd(3), or
     delayed loads. The	use of any of these, delays the	loading	of a shared
     object (and the objects on	it's liblist) until it is actually referenced.
     The most convenient is the	-delay_load option to ld. All three require
     that there	be no references from any other	objects' data section to the
     delay loaded shared object.

FREQUENTLY ASKED QUESTIONS
List of	Questions:

   1)  What is DSO?
   2)  How do dynamic shared objects compare with shared libraries?
   3)  How do I	maintain binary	compatibility between versions of
     dso's?"

   4)  Under which versions of the OS can I use	DSO?
   5)  What object-file	format does DSO	use?
   6)  How do I	install	the tools so I can use DSO on my system?
   7)  How do I	build an executable that uses a	shared object?
   8)  How do I	build an executable that doesn't use shared
     linking?"

   9)  How do I	tell if	an executable will use dynamic linking?
   10) How do I	build a	shared object?
   11) Where does the system look for shared objects at	runtime?
   12) What is Quickstart?
   13) What is the so_locations	file?
   14) What directives can be put in a so_locations file?
   15) What is /usr/lib/so_locations?
   16) If I don't have a valid so_locations, can I generate one	from
     all the .so's in, say, /usr/lib?"

   17) How expensive is	it (at runtime)	to NOT use the
     -update_registry option?"

   18) How and when will Quickstart be used?
   19) What about run-time loading under user control?
   20) What benefits will I get	from DSO?
   21) What costs are associated with DSO?
   22) What is the -KPIC option?
   23) Must main programs which	want to	use DSO's use -KPIC for
     compilation?"

   24) How do I	change my assembly language sources to use -KPIC?
   25) Can I mix IRIX 4	static shared libraries	with DSO's?
   26) What options do I have when building a shared object?
   27) What pitfalls should I know about which are associated with
     DSO?"

   28) What should I do	about a	GOT overflow?
   29) How are multiple	versions of DSO's supported?
   30) Why are the global objects in my	C++ DSO	not being initialized?
   31) Where can I find	more documentation on DSO?
   1)  What is DSO?
     DSO stands	for Dynamic Shared Objects.  DSO provides a capability similar
     to	static shared libraries	under Cypress and earlier versions of the
     IRIX, e.g., it gives applications the ability to share the	text of
     heavily used libraries, which need	not be included	in the executable
     file.  However DSO	has two	important distinctions from static shared
     objects.

   2)  How do dynamic shared objects compare with shared libraries?
     First, a dynamic shared object contains only position-independent code,
     so	that it	may be mapped into the virtual address space of	different
     processes at different addresses and still	be shared.  Second, dynamic
     shared objects, and indeed	the executable itself are mapped in by a
     runtime loader, rld, which	resides	in memory in the same address space as
     the executable.  This gives the system the	ability	to change the binding
     of	symbols	during executions, at the request of the executing program.
     This capability should prove useful across	a large	segment	of
     applications.

   3)  How do I	maintain binary	compatibility between versions of dso's?
     As	long as	the shared objects maintain the	same exported symbols, or
     perhaps add new symbols without removing any or changing semantics, and
     don't change exported structures, they will be binary compatible.
     Ordering of symbols, routines, are	irrelevant, as global data, etc.  We
     are working on a system called Delta-C++ which should allow you to	add to
     exported classes without recompiling.

   4)  Under which versions of the OS can I use	DSO?
     DSO is available under IRIX versions 5.0 and later.  Programs built with
     DSO will not work on earlier version of IRIX.

   5)  Which object-file format	does DSO use?
     DSO uses the ELF object file format, as defined in	the SVR4 ABI.  ELF
     objects cannot be run under IRIX 4.0.5 or earlier.

   6)  How do I	install	the tools so I can use DSO on my system?
     IRIX 5.0 and later	releases all support/use DSO's.	 In order to compile
     and build shared objects you will need to have the	Developer's option
     installed.

   7)  How do I	build an executable that uses a	shared object?
	      cc myfile.c -lmine

     This will link you	with libmine.so	and also with libc.so.1, if either are
     available.	 If no libmine.so is available,	but there is a libmine.a, the
     libmine.a will be used along with libc.so.1, and you will still get
     dynamic linking.  If you wish to be explicit, add the -call_shared	flag
     to	the cc line:

	      cc -call_shared myfile.c -lmine

   8)  How do I	build an executable that doesn't use shared linking?
     Use the -non_shared flag:

	      cc -non_shared myfile.c -lmine
   9)  How do I	tell if	an executable will use dynamic linking?
     elfdump -o	shows you the ELF program header.  This	contains all the
     information necessary for exec and	rld to run the program/shared object.
     Only a.outs which use dynamic linking will	have a PHDR, INTERP, or
     DYNAMIC entry.

     Here's an example,	and a more detailed description	of this	stuff.

     % elfdump -o /bin/cat

		  ***PROGRAM HEADER***
Type	 Offset	     Vaddr	Paddr	  Filesz      Memsz	 Align RWX
   PHDR	0x00000034 0x00400034 0x00400034 0x000000c0 0x00000000 0x00000004 r--
 INTERP	0x00000100 0x00400100 0x00400100 0x00000009 0x00000009 0x00000004 r--
REGINFO	0x00000110 0x00400110 0x00400110 0x00000018 0x00000018 0x00000004 r--
DYNAMIC	0x00000150 0x00400150 0x00400150 0x00000a70 0x00000a70 0x00000010 r--
   LOAD	0x00000000 0x00400000 0x00400000 0x00003000 0x00003000 0x00001000 r-x
   LOAD	0x00003000 0x10000000 0x10000000 0x00001000 0x00001290 0x00010000 rwx

     Each line is an entry in the program header, and refers to	a "segment" of
     the file.

     PHDR points to the	program	header itself within the file. Only
	  executables which use	dynamic	linking	will have this field.

     INTERP
	  points to a place in the file	where the name of the interpreter
	  required for this program is to be found.  For any ABI-conforming
	  object, this name will be "/usr/lib/libc.so.1".

     REGINFO
	  points to a place in the file	where information about	register setup
	  can be found.	 Currently this	mostly consists	of the correct gp
	  value	for this object.

     DYNAMIC
	  points to the	information in the file	which is needed	by rld to
	  execute it correctly.	 This information includes the liblist,	a
	  symbol table,	and other information.

     LOAD points to segments that are to be mapped into	the memory image.

     The columns give various information about	each segment.

     Offset
	  is the offset	in the file to the beginning of	the segment.

     Vaddr
	  is the virtual address of the	beginning of the segment in the	memory
	  image	of the file, ASSUMING that it was mapped as described in the
	  LOAD entries
     Paddr
	  is the same as Vaddr in our implementation.

     Filesz
	  is the size of the segment in	the file.

     Memsz
	  is the size of the segment in	the memory image.  When	this is	larger
	  it is	assumed	to be zero-filled.

     Align
	  is the alignment required by this section.  If an segment is to be
	  mapped somewhere into	memory other than at Vaddr, the	new address
	  must be congruent to Vaddr modulo the	alignment.  In the example
	  above, the first segment must	always be loaded at a page boundary,
	  and the second must always be	loaded at a 64K	boundary.

     RWX  specifies the	protections r(ead), w(rite), or	x(ecute) for the
	  segment.

     Programs which are	linked -non_shared do not have a PHDR, INTERP, or
     DYNAMIC section.  Thus elfdump -o is a convenient method to determine if
     a program is linked -non_shared or	not.

   10) How do I	build a	shared object?
     To	begin with, build a .o or .a which contains all	the routines you want
     to	have in	your .so (shared object).  This	can be done with cc -c and ar.
     Then invoke ld with the -shared flag. Normally the	extension .so is used
     to	designate shared objects.

     Here is an	example:

	 cc -c myobj.c
	 ld -shared myobj.o -o myobj.so

	 -or-

	 <build	libmine.a the usual way.>
	 ld -shared -all libmine.a -o libmine.so

     The -all flag in the second example tells ld to include all the routines
     in	the library.  This is necessary	since there are	no undefined
     references	(in a main, say) which is the usual way	that ld	knows to
     include files from	an archive.

   11) Where does the system look for shared objects at	runtime?
     The search	path for shared	objects	is acquired in the following order:

     1)	the path of the	shared object if given in the liblist,
     2)	in any directories specified via the
	  -rpath flag when the executable was built

     3)	in any directory specified by the LD_LIBRARY_PATH environment
	  variable, if it is defined

     4)	in the directories in the default path
	  (/usr/lib:/lib:/lib/cc:/usr/lib/cc)

     If	the _RLD_ROOT environment variable is defined, then its	value is
     appended to the front of any path specified by -rpath and the default
     path.  _RLD_ROOT itself is	also a colon(:)	separated list.

     See the rld(1) manpage for	details.

   12) What is Quickstart?
     Quickstart	is an optimization. Using the so_locations file, each shared
     object is pre-relocated by	ld, as if it had been loaded at	the address in
     the so_locations file.  That way, if nothing unusual happens when we
     start up the application, all the shared objects will map at their
     Quickstart	addresses, and rld will	not need to do a relocation pass over
     them.

     If	for some reason	more than one shared object wishes to map the same
     address, rld will move one	of them	to an unused address and perform a
     relocation	pass to	fix up the address references.

     If	one or more of the shared objects linked against at static link	time
     has changed by the	time the program executes, rld will need to do extra
     work to ensure that symbols have been resolved to their proper value.

   13) What is the so_locations	file?
     In	the directory in which you build a shared object, after	you've
     actually built one, you will notice a file	named so_locations.

     It	is a registry of shared	objects.  It maintains the default or
     Quickstart	addresses of a group of	shared objects which are to cooperate
     by	not having their default location overlap with one another.  It	is
     generated and updated by ld each time it builds a shared object.

   14) What directives can be put in an	so_locations file?
     Comment line
	  so_name [ :st	= { .text | .data | $range } base_addr,padded_size : ] *

     where
	  so_name	  full path name (or trailing component) of a
			  shared object
	  st		  string identifying start of the segment description
	  .text	| .data	  segment types: text or data
	  $range	   limit the range of address that can be used
	  base_addr	  address where	the segment starts
	  padded_size	  padded size of the segment
     The following directives control the placement of new shared objects:

	  $text_align_size=<align>  padding=<pad-size>
	  $data_align_size=<align>  padding=<pad-size>
	      These two	directives specify the alignment and padding
	   requirements	for text and data segments respectively.
	   The size value in so	location is calculated based on:
	      (section size + padding) aligned to the section align size
	      The align	values for text	and data as well as the	padding
	      values must be aligned to	a bucket size. If not, ld will
	   generate a warning message and align	these values to	bucket
	   size.

	  $start_address=<addr>
	      Specifies	where to start looking for addresses to	put shared
	      objects.

	  $data_after_text=[ 1 | 0 ]
	      Instructs	the linker to place data immediately after the text
	      at specified text	and data alignment requirements.
	      We set the data_after_text to 0 if the argument of this directive
	      is missing.

     Also, when	building a dso with the	-check_registry	or -update_registry
     flag, and if there	is already an entry corresponding to this dso in the
     so_location file, the linker will try to assign the same addresses	for
     text and data.  However, if the size of the dso changes and does not fit
     in	the specified location any more, the linker will search	for another
     spot that fits.  If the optional $range comment is	given, the linker will
     only place	the dso	in the specified range of addresses.  If there is not
     enough room, an error will	be given.

   15) What is /usr/lib/so_locations?
     This file represents the default layout for the system shared objects.
     Developers	who build shared objects may find it interesting to consult
     this file,	in order to avoid collisions between their shared objects and
     system shared objects.  This file is absolutely irrelevant	to users who
     merely run	programs which use shared objects.

     There are two options which are relevant, -update_registry, and <file>
     looks at <file> and builds	the current .so	at a location which doesn't
     conflict with anything in the file	(unless	the current one	is listed.  -
     check_registry does not write to <file>.  -update_registry	<file> will
     consult <file> as with -check_registry, but will attempt to write an
     entry for the .so being built into	<file>.	 If <file> is not writable, -
     update_registry turns into	If <file> is not readable -check_registry and
     -update_registry are ignored.

   16) If I don't have a valid so_locations file, can I	generate one from all
     the .so's in, say,	/usr/lib?
     There is no convenient method to do so.  There is no guarantee that all
     the .so's in /usr/lib have	been coordinated so that a consistent
     so_locations file can be made from	them.  So it is	better to get the one
     that a particular release was made	with.

   17) How expensive is	it (at runtime)	NOT to use -update_registry option?
     The costs are all startup costs.  It is very difficult to say how much a
     particular	executable will	suffer since it	depends	on which shared
     objects the program uses and whether they have been Quickstarted for the
     same address.  When there is a conflict between two objects, one will be
     moved, which means	that all addresses referring to	names in that object
     need to be	relocated.

   18) How and when will Quickstart be used?
     Normally, the linker will use Quickstart unless there are unresolved
     symbols at	static link time.

     In	every executable and every shared object is a list of objects which
     were looked at at static link time	-- when	the object was made.  This
     list also contains	timestamps and checksums for each of the objects.
     Various levels of extra work are required if the timestamp	or checksum
     has changed in the	library	at run-time.

   19) What about run-time loading under user control?
     We	support	an interface known as libdl, which allows users	to dynamically
     load their	own shared objects as needed. The calls	are

     dlopen() -- open a	new shared object and get a "handle" to	it.

     dlsym()  -- find the value	of a name defined in an	object.

     dlclose()-- close a shared	object.

     dlerror()-- report	errors.

     sgidladd()	-- functions much like dlopen however it exposes
	  all symbols to the rest of the program.

     Consult the individual manpages for details.

   20) What benefits will I get	from DSO?
     Executables linked	with shared objects will be smaller since the shared
     objects are not part of the executable file image.

     Executables which use a shared object need	not be relinked	if a shared
     object is changed -- once the updated shared object is installed, the
     executable	will pick it up	automatically.

     Shared libraries are much easier to build,	use, and debug than static
     shared libraries.

     DSO allows	application designers to make more machine-independent
     software.	System-dependent routines can be given a uniform interface and
     a shared object which implements that interface can be built for each
     different platform.  Then an actual application can be shipped as-is
     ("shrink-wrapped" software) to various platforms and run on them all.

     DSO gives applications the	ability	to change the binding of symbols at
     run time, under user control.

   21) What costs are associated with DSO?
     A shared object incurs two	costs, both against performance.

     At	startup, there will be a startup cost while rld	maps in	the various
     objects, performs symbol resolution, etc.	We believe this	cost is	small
     compared to the time it takes to contact the X server, for	example.
     Quickstart	will reduce this time for smaller applications.

     A shared object's text must be PIC	(position independent code).
     PICification is accomplished by the code generator	(ugen) and assembler
     (as), when	the -KPIC flag is specified.  This is the default However, PIC
     code is necessarily slower. Experiments have indicated that this speed
     reduction is usually less than 5 percent, but can be as much as 15
     percent.  depending on the	application.  PIC code seems to	be worst on
     very small	leaf routines which access global data.

   22) What is the -KPIC option?
     This the default and should not be	seen anymore.  This flags tells	the
     code generator and	assembler to generate PIC directly.  The result	is an
     object file that can be put into a	DSO without further modification

	      cc -KPIC -c foo.c

     will give you a PIC object	foo.o.	Other drivers (cc, pc, f77, and	as)
     also accept the -KPIC option.  This is the	default.

     Routines written in assembly languages need to be modified	before -KPIC
     can be used. See the question below.

     PIC objects generated by using -KPIC must be compiled -G 0.

   23) Must main programs which	want to	use DSO's use -KPIC for	compilation?
     Yes.  DSO's use -KPIC so that position-independent	code will be
     generated.	 Main programs are not generally position-independent, but
     must still	use the	DSO calling convention when calling a routine which is
     defined in	a DSO. In particular, this means that a	main program must have
     a GOT, and	the code which is generated must use it.  Therefore, modules
     which will	become part of main programs must be compiled -KPIC as well as
     modules which become part of DSO's.

   24) How do I	change my assembly language sources to use -KPIC?
     The following refers to the older 32 bit abi using	ucode compilers.  For
     n32 and 64	bit abi	information, look at the information and pointers in
     the abi(5)	manpage.

     Several new assembler directives are added	to support generation of PIC.
     You should	also get yourself familiar with	the MIPS ABI Supplement	and
     the PIC coding model it describes.	 In addition, files which are to be
     assembled with -KPIC must also be -G 0.  This is normally turned on by
     the driver	by default.

     Note that with the	exception of (a) and (d), all other directives
     described below will be ignored when -KPIC	is not explicitly specified.
     Also, item	(d), ".gpword",	will be	turned into ".word". The result	will
     be	a NON-PIC version of the same routine.

     a)	.option	pic2

     This directive forces the assembler to mark the output object file	"PIC"
     and activates the following directives.  It overrides the command line
     argument.	Normally, you don't need to specify this directive.  Instead,
     you should	use the	-KPIC or -non_shared flags to toggle between
     generating	PIC or non-PIC.

     Note that even though -KPIC will be made the default for the high-
     language driver (cc/pc/f77) in future releases, it	will *NOT* be the
     default for assembly sources.  You	will always have to explicitly specify
     -KPIC for compiling .s files.

     b)	.cpload	reg

     This directive expands into three instructions that sets the gp register
     to	the context pointer value for the current function.  The three
     instructions are:
	  lui  gp,_gp_disp
	  addui	    gp,gp,_gp_disp
	  addu gp,gp,reg

     _gp_disp is a reserved symbol defined by the linker to be the distance
     between the lui instruction and the context pointer.  This	directive is
     required at the beginning of each subroutine that uses the	gp register.

     You must add this directive at the	beginning of every procedure, with the
     exception of leaf-procedures that do not access any global	variables, and
     procedures	that are static	(i.e., not marked .globl or .extern).

     c)	.cprestore offset

     This directive causes the assembler to issue
	       sw   gp,offset(sp)
     at	the point where	it appears.  Additionally, it causes the assembler to
     emit
	       lw   gp,offset(sp)
     after every jump-and-link (jal) or	branch-and-link	(bal) operation,
     thereby restoring the gp register after function calls.  The programmer
     is	responsible for	allocating the stack space for the gp.	This space
     should be in the saved register area of the stack frame to	remain
     consistent	with MIPS' calling and debugger	conventions.

     d)	.gpword	local-sym

     This directive is similar to .word	except that the	relocation entry for
     local-sym has the R_MIPS_GPREL32 type.  After linkage, this results in a
     32-bit value that is the distance between local-sym and the context
     pointer (i.e. the gp).  local-sym must be local.  It is currently used
     for PIC switch tables.

     e)	.cpadd reg

     This adds the value of the	context	pointer	(gp) to	reg.

     EXAMPLES:
	  This is a simplified version of the "hello world" program:
	  --------------------------------------------------------------
	       .option	 pic2
	       .data
	       .align	 2
	  $$5:
	       .ascii	 "hello	world\X0A\X00"
	       .text
	       .align	 2
	  main:
	       .set  noreorder
	       .cpload	 $25
	       .set  reorder
	       subu $sp, 40
	       sw   $31, 36($sp)
	       .cprestore     32
	       la   $4,	$$5
	       jal  printf
	       move $2,	$0
	       lw   $31, 36($sp)
	       addu $sp, 40
	       j    $31
	  ----------------------------------------------------------------
	  The actual instructions generated by the assembler will be:

	       lui  gp,0      #
	       addiu	 gp,gp,0	# generated by .cpload
	       addu gp,gp,t9  #
	       lw   a0,0(gp)  #	gp-relative addressing used
	       lw   t9,0(gp)  #	t9 is used for func. call
	       addiu	 sp,sp,-40
	       sw   ra,36(sp)
	       sw   gp,32(sp) #	from .cprestore
	      jalr  ra,t9	   # jal is changed to jalr
	       addiu	 a0,a0,0
	       lw   ra,36(sp)
	       lw   gp,32(sp) #	activated by .cprestore
	       move v0,zero
	       jr   ra
	       addiu	 sp,sp,40
	       nop
	  ----------------------------------------------------------------

     NOTE:

     The MIPS's	ABI required register t9 ($25) be used for indirect function
     call, so .cpload should always use	$25.  No reorder mode should also be
     used.  Also, programmers should make sure that t9 is dead before any
     function call.

     If	your program uses an indirect jump (jalr), you must also use t9	as the
     jump register.

     If	you have an unconditional jump to an external label:
	       j  _cerror
	 you have to rewrite it	into indirect jump via t9, i.e.:
	       la t9,_cerror
	       j  t9

     If	you use	branch-and-link	(bal) instruction, and if the target procedure
     begins with a .cpload, you	have to	specify	an alternate entry point:

	  foo: .set noreorder #	callee
	       .cpload	 $25
	       .set reorder
	  $$1: ...	      #	alternative entry point
	       ...
	       j    $31	      #	foo returns

	  bar: ...	      #	caller
	       ...
	       bal  $$1	      #	by-pass	the .cpload
	       ...

     This is very important because .cpload assumes register $25 contains the
     address of	foo, but in this case $25 is not set up.  Note that since both
     foo and bar reside	in the same file, they must have the same value	for
     $gp.  So the .cpload instructions can be and must be bypassed.  However,
     since foo can still be called from	outside, the .cpload is	still
     required.

     Alternatively, if you don't want to have an alternate entry point,	you
     can set up	register $25 before the	bal:
	       la   t9,foo
	       bal  foo
	 but this will be less efficient.

     position-independent jump table (or any table of text addresses).
     Entries of	the address table created by .gpword are converted into
     displacement from the context pointer.  To	get the	correct	text address,
     .cpadd should be used to add the value of gp back to them.	 Since the gp
     is	updated	by the run-time	linker,	the correct text address can be
     reconstructed regardless of the location of the dso.

   25) Can I mix IRIX 4	static shared libraries	with DSO's?
     We	do not anticipate ever allowing	an a.out to use	both static shared
     libraries and dso.

   26) What options do I have when building a shared object?
     If	you specify the	flag -B	dynamic	while linking a	shared object, symbols
     in	the shared object will be resolved differently than the	default
     linkage convention.  In particular, the runtime linker will always	try to
     resolve any symbols referenced in that object to symbols defined in that
     object first, instead of looking for definitions in objects in the	order
     specified on the link line.

     The effect	of this	is to make all symbols defined and used	in such
     objects non-preemptable.  Ordinarily a such symbol	definitions could be
     preempted by a definition in an earlier shared object, but	when -B
     symbolic is specified, this is not	the case.

   27) What pitfalls are associated with DSO?
     Behind most of the	surprises that users will get is the fact that linking
     semantics are fundamentally different, but	only in	a subtle way.  Let us
     suppose that your program links with three	libraries, libA, libB and
     libC, in that order.  Further suppose that	both libA and libC define some
     symbol x, but don't use it.  Furthermore, let us suppose that libB
     contains a	reference to x.	 Archive linking (the old way) will resolve
     B's reference to x	to the definition in C,	whereas	shared object linking
     will resolve B's reference	to x to	the definition in A.

     Why the difference?  With archive linking,	when libA is examined, there
     is	no outstanding reference to x, hence the definition of x is not
     extracted from the	archive.  Later	when libC is examined, there is	a
     reference to x, so	it is loaded.

     With shared objects, all the constituent object files have	been joined
     into one object, so all symbol definitions	are always present.  The
     resolution	rule is	simple,	take the definition in the object listed
     first. Thus the definition	in libA	is used.

     Another sort of surprise is the "runtime dangling reference".  It is
     altogether	possible to build and link an application with no errors or
     even warnings, only to get	a message from rld stating that	your program
     has unresolvable symbols.

     What's going on?  Well, if	you build a shared object as part of your
     program, the linker will not normally complain about undefined symbols
     during a link of a	shared object.	This is	because	undefined symbols are
     expected during such a build and are perfectly acceptable.	 But if	the
     main program does not use a symbol, it does not get flagged as undefined
     during static linking.  Thus the runtime "surprise".  You can use the -
     no_unresolved flag	to the linker to avoid such surprises.

     Now we get	to a nasty pitfall which can be	avoided	by some	cleverness in
     building a	shared object.	If a particular	object in an archive has an
     external reference	to a data symbol (which	it expects to be defined in
     main, libl.a, for example)	the linker would not try to resolve that
     external unless the object	file in	question was actually referenced by
     the main program.	Now if that archive is turned into a shared object
     naively, the external data	reference must be resolved whenever ANY
     function in the shared object is used, even if no function	in the object
     file in question is ever called and no use	is made	of the external	data
     symbol in question.

     This can lead to a	scenario where a user has a link that worked with the
     archives, but builds a program which gets nuked by	the runtime linker
     under the new scheme of things.  I	believe	that it	is a very bad idea for
     us	to convert libraries. such as libl.a, which contain external data
     symbols, to shared	objects	naively.

     One thing that can	be done	is to split the	archive	into several shared
     objects which are placed on the liblist of	a "master" shared object.
     Since rld will not	by default try to resolve data symbols until the first
     call is made to a particular object we can	create the situation where no
     attempt to	resolve	the offending external data symbol is made until a
     call is made to the object	in which it is referenced.

     Here's an example of how that works: Let us suppose that
     has_extern_data.o is an object with an undefined external in it which
     resides in	the archive libxyz.a  Here is how to isolate that external
     data reference:

     First make	has_extern_data.o into a shared	object all its own.

	   % ar	x libxyz.a has_extern_data.o
	   % ld	-shared	has_extern_data.o -o has_extern_data.so

     Now, make libxyz.so, excluding has_extern_data.o from being included
     directly, but instead putting it in the liblist of	libxyz.so

	 % ld -shared -all -exclude has_extern_data.o libxyz.a has_extern_data.so      -o libxyz.so

   28) What should I do	about a	GOT overflow?
     By	default, addresses are loaded out of the Global	Offset Table (GOT)
     using a 16	bit offset from	a context pointer.  This means that the	size
     of	the GOT	is limited (by default)	to 64K bytes, or about 16 K symbols.
     When there	are too	many symbols referenced	by a DSO (or a.out) the	linker
     issues the	messag "GOT overflows"	and will specify an object file	which
     references	the symbol which is "out of reach".

     SGI recommends that when developers encounter this	problem, they attempt
     to	split the DSO or a.out in question into	several	smaller	DSO's, each of
     which can conform to the GOT size limit.  Maximum performance can be
     achieved this way.

     However, as an alternative, developers may	wish to	use the	-Wl,-multigot
     flag on the compile line or -multigot on the link line.

     However, as a last	resort,	developers may wish to use the -xgot compile-
     time flag to tell the compiler to issue a different (and slower) code
     sequence uses a 32-bit offset.  This will allow the GOT to	contain	up to
     1G	entries.  However, it is critical that every object linked into	a
     final DSO or a.out	be compiled with -xgot turned on, otherwise code may
     have been generated which will not	work with an extended GOT.  However,
     files compiled with -xgot may be linked into a DSO	or a.out which has a
     GOT that does not exceed the 8K symbol limit for 64-bit objects (16K for
     32-bit objects) and will work correctly, if somewhat slower.  The GOT
     size of any shared	objects	linked is irrelevant.

     The directory /usr/lib/xgot contains the extended-GOT versions of those
     objects which SGI has built both normally and -xgot. If a system or third
     party archive contains small GOT objects which are	needed in an extended
     GOT link, a developer can take the	following steps: 1) Look in
     /usr/lib/xgot to see if an	extended GOT version exists.  2) Turn the
     archive into its own shared object, thus isolating	it from	the extended
     GOT binary. 3) contact the	archive	provider.  In a	few cases (crt1.o,
     crtn.o, c++init.o,	and fixade.o), where the performance issues were
     minimal,  the default objects in /usr/lib are in fact built large GOT.

     To	check if objects were compiled with -xgot, one can use elfdump -f.

   29) How are multiple	versions of DSO's supported?
     IRIX 5.0.1	(Compilers v3.16) and later supports the ability to tag	shared
     objects and executables with a version number.  This is intended to
     support interface changes.	 Details are below; items marked (SGI ONLY) do
     not apply to MSIG ABI binaries, but only to binaries generated on IRIX
     without the -abi flag turned on.

     Versioning	of Shared Objects.

     QUICK OVERVIEW

     In	order for a shared object to be	versioned in the future
     the following needs to be done:

     * Version strings consist of 3 parts and a	dot: The string	"sgi",
       a decimal number	(the major number), a dot, and a decimal number
       (the minor number).

     * Add the command -set_version sgi1.0 to the command to build
       the shared object (cc -shared, ld -shared, etc.).

     * (Future)	Whenever you make a COMPATIBLE change update the minor version
       number (the one after the dot), and add the latest version string
       to colon-separated list of version strings, e.g., -set_version
       sgi1.0:sgi1.1:sgi1.3

     * (Future)	Whenever you make an INCOMPATIBLE change, update the
       major version number.  Pass this	as the version list, e.g.,
       -set_version sgi2.0.  Change the	filename of the	OLD shared object
       by adding a dot followed	by the previous	major number to	the filename
       of the shared object.  DO NOT CHANGE the	soname of the object.
       No change to the	file contents are necessary or desirable.  Simply
       rename the file.

     HOW IT ALL	WORKS

     * Versioning will only be available for NON-ABI executables.
       The current ABI does not	require	objects	to have	versioning, nor
       does it require systems to pay attention	to versioning.	It does
       allow objects to	contain	version	strings, but does not require
       systems to do anything with this	information.

     * NON-ABI compliant executables will have a SGI_ONLY bit turned
       on in the .dynamic section.  This flag will be understood and
       reported	by elfdump.  Only executables with this	flag on	will
       get the versioning treatment described below.  This flag	will
       be on by	default.

     * When an executable is linked against a shared object, the last
       entry of	the shared object's version string is recorded in the
       executable as part of the liblist.  This	can be examined	by
       elfdump -Dl.

     * When an executable is linked, the user may specify -require_minor or
       -ignore_minor for each shared object linked against.  If
       -require_minor is specified, a bit will be set in the flags field of
       the liblist entry for the shared	object in question.  The default
       is -ignore_minor.

     * When an executable (ABI or SGI_ONLY) is run rld will look
       for the proper filename in its usual search routine.

     * (SGI_ONLY) If a file with the correct name is found the
       version string in the liblist is	compared to the	list
       of version strings in the shared	object.	 If the	REQUIRE_MINOR bit
       is set in the liblist entry, and	there is an exact match	between	the
       version string in the depender and one of the strings in	the version
       list of the dependee, then that library is used.	 If the
       REQUIRE_MINOR bit is clear, and if there	is a match of major
       versions, then that library is used.

     * (SGI_ONLY) If no	proper match is	found, a new soname is built
       by taking the soname found in the executables liblist, and the
       major number found in the version string	corresponding to that
       liblist entry, and putting them together	as <soname>.<major>
       This is searched	for in the same	way as above. Version strings are
       matched in exactly the same way as described above.

   30) Why are the global objects in my	C++ DSO	not being initialized?
     Did you link your DSO using the CC	command	(instead of using ld
     directly)?	See the	NOTE: After the	first example in this man page,	that
     discusses how to create a C++ DSO.

   31) Why are some libraries only available as	a DSO, where as	other
     libraries are available as	both a DSO and an archive?
     The ABI specifies which .so's must	be on every system.  The converse of
     that is that no one can assume that any other .so is on an	ABI conforming
     system. Libraries explicitly called out in	the MIPS ABI are considered
     part of the system	interface; and the decision was	made to	only ship such
     system interfaces in DSO form. Libraries that are not specified in	the
     MIPS ABI must also	be supplied in archive form to generate	MIPS ABI
     compliant binaries	using these libraries.

     For example the libraries:	libX11.so,and libc.so are explicitly called
     out in the	MIPS ABI making	the DSO	version	of Xlib	and libc a system
     interface.	Other examples are libsocket.so	and libdl.so which are also
     only supplied as DSOs.

     Archive versions of libXt.a, libXm.a,libm.a libmalloc.a, etc...  are
     supplied because shared library versions of these libraries are not
     specified in the MIPS ABI,	therefore they are not guarenteed to exist on
     all ABI conforming	systems.

   32) Where can I find	more documentation on DSO?
     Besides the other manpages	mentioned below, System	V Application Binary
     Interface and System V Application	Binary Interface -- MIPS Processor
     Supplement	are both good sources of DSO implementation details.

SEE ALSO
     abi(5), rld(1), ld(1), elf(5), elfdump(1),	dlopen(3), sgidladd(3)

UPDATES
     This man page is periodically updated;  the last update done on
     1993/11/08	for IRIX 5.2.